package com.jake.groovy.ex2;
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
import groovy.util.ResourceException;
import groovy.util.ScriptException;

import java.io.File;
import java.io.IOException;

import javax.swing.JMenu;
import javax.swing.JOptionPane;

public class ScriptConnector {
    Binding      binding;  // The 'binding' makes instances of the application objects available as 'variables' in the script
    SDEGuiWindow window;   // The main application window, the GUI in general
    String[]     roots;    // A list of directories to search for Groovy scripts (think of it as a PATH).

    public ScriptConnector(Workspace workarea, SDEGuiWindow window) {
        roots     = new String[]{System.getProperty("user.home"), "." };   // The root list is filled with the locations to be searched for the script
        Binding  scriptenv = new Binding();    // A new Binding is created ...

        scriptenv.setVariable("workarea", workarea);  // ... and filled with two 'variables': the workarea to work on
        scriptenv.setVariable("SDE", this);           // and the current ScriptConnector instance as API provider.
        this.binding = scriptenv;
        this.window  = window;
    }

    // Method to show Groovy related errors/warnings in a dialog window.
    public void showWarning(String message) {
        JOptionPane.showMessageDialog(window, message, "Groovy-error", JOptionPane.WARNING_MESSAGE);
    }


    // This is the main method called from the application code to start the Groovy integration
    public void runGuiComponentScript(String filename) {
         GroovyScriptEngine gse = null;
         try {
             gse = new GroovyScriptEngine(roots);   // instanciating the script engine ...
         } catch (IOException ioe) {
             ioe.printStackTrace();
             showWarning("I/O-Exception in starting Groovy engine. Message is:\n"
                         + ioe.getMessage()
                         + "\n" + prepareStackTrace(ioe));
         }

         if (gse != null) {
             try {
                 gse.run(filename, binding);      // ... and running the specified script
             } catch (ResourceException re) {
                 re.printStackTrace();
                 showWarning("ResourceException in calling groovy script '" + filename +
                             "' Message is:\n" +re.getMessage()
                             + "\n" + prepareStackTrace(re));

             } catch (ScriptException se) {
                 se.printStackTrace();
                 showWarning("ScriptException in calling groovy script '" + filename +
                             "' Message is:\n" +se.getMessage()
                             + "\n" + prepareStackTrace(se));
             }
         }

     }



    // prepare a stacktrace to be shown in an output window
    private String prepareStackTrace(Exception e) {
        Throwable exc = e;
        StringBuffer output = new StringBuffer();
        collectTraces(exc, output);
        if (exc.getCause() != null) {
           exc = exc.getCause();
           output.append("caused by::\n");
           output.append(exc.getMessage());
           output.append("\n");
           collectTraces(exc, output);
        }
        return output.toString();
    }

    private void collectTraces(Throwable e, StringBuffer output) {
        StackTraceElement[] trace = e.getStackTrace();
        for (int i=0; i < trace.length; i++) {
            output.append(trace[i].toString());
            output.append("\n");
        }
    }

    // ----------------- API to be used inside scripts --------------------

    // create a new dialog to display textual output from running scripts
    public ScriptOutputDialog newOutputDialog(String title, String tabTitle) {
        return window.newOutputDialog(title, tabTitle);
    }

    // get the panel instance prepared to contain customised GUI elements, e.g. buttons
    public DynamicPanel getDynpanel() {
        return window.getDynamicPanel();
    }

    // get the user menu instance to add custom items and submenus to.
    public JMenu getUsermenu() {
        return window.getSDEUserMenu();
    }

    // create a process to run a shell command in a given directory
    public Process exec(String command, File inDir) {
        Process proc = null;
        try {
            proc = Runtime.getRuntime().exec(command, null, inDir);
        } catch (Exception e) {
            displayExecError(e.toString());
        }
        return proc;
    }

    // create a process to run a shell command
    public Process exec(String command) {
        Process proc = null;
        try {
            proc = Runtime.getRuntime().exec(command);
        } catch (Exception e) {
            displayExecError(e.toString());
        }
        return proc;
    }

    private void displayExecError(String message) {
        ScriptOutputDialog win = window.newOutputDialog("Groovy Error", "Error during exec");
        win.addTabPane("error");
        win.println("error", message);
    }

}